home *** CD-ROM | disk | FTP | other *** search
- ;/* InOutCTRL-C.c - Execute me to compile me with Lattice 5.10b
- LC -b0 -cfistq -v -y -j73 InOutCTRL-C.c
- Blink FROM LIB:c.o,InOutCTRL-C.o TO InOutCTRL-C LIBRARY LIB:LC.lib,LIB:Amiga.lib,lib:debug.lib
- quit ;*/
-
- /* (c) Copyright 1992 Commodore-Amiga, Inc. All rights reserved. */
- /* The information contained herein is subject to change without notice, */
- /* and is provided "as is" without warranty of any kind, either expressed */
- /* or implied. The entire risk as to the use of this information is */
- /* assumed by the user. */
-
-
- /* InOutCTRL-C.c uses packets to copy the standard input channel to the */
- /* standard output channel using asynchronous I/O. This example does a better */
- /* job checking for a user break than the accompanying example, CompareIO.c. */
-
- #include <exec/types.h>
- #include <dos/dosextens.h>
-
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/alib_stdio_protos.h>
-
- #ifdef LATTICE
- int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
- void chkabort(void) { return; }
- #endif
-
-
- #define BUFSIZE 8192
-
- UBYTE *vers = "\0$VER: InOutCTRL-C 37.9 Nov-12-92";
-
- void MainLoop(void);
-
- extern struct Library *DOSBase;
-
- struct MsgPort *myport;
- ULONG portsignal, signals, sigmask;
-
- struct FileHandle *in, *out;
- struct DosPacket *sp_read, *sp_write;
-
- UBYTE buf1[BUFSIZE], buf2[BUFSIZE];
-
- void main(void)
- {
- if (DOSBase->lib_Version >= 37) /* 2.0 only */
- {
- if (myport = CreateMsgPort())
- {
- if (in = (struct FileHandle *)BADDR(Input())) /* Need file handle to */
- { /* get to Handler process */
- if (out = (struct FileHandle *)BADDR(Output()))
- {
- if (sp_read = AllocDosObject(DOS_STDPKT, NULL)) /* Allocate two */
- { /* StandardPackets: one */
- if (sp_write = AllocDosObject(DOS_STDPKT, NULL)) /* for reading, and one */
- { /* for writing. */
-
- sp_read->dp_Type = ACTION_READ; /* Fill out the ACTION_READ packet. */
- sp_read->dp_Arg1 = in->fh_Arg1;
- sp_read->dp_Arg2 = (LONG)buf1; /* The buffer to fill in. */
- sp_read->dp_Arg3 = BUFSIZE; /* The size of the Arg2 buffer. */
-
- /* When AllocDosObject() allocates a StandardPacket, it takes */
- /* care of linking together the Message and DosPacket. */
- /* AllocDosObject() points the DosPacket's dp_Link field at */
- /* the StandardPacket's Message structure. It also points */
- /* the Message's mn_Node.ln_Name field at the DosPacket: */
- /* sp_read->dp_Link = sp_Msg; */
- /* sp_Msg->mn_Node.ln_Name = (STRPTR)sp_read; */
-
-
- if (!((out->fh_Arg1) && (in->fh_Arg1))) /* Don't bother if in or */
- return; /* out uses NIL: */
-
- SendPkt(sp_read, in->fh_Type, myport); /* Send initial read request. */
-
- portsignal = 1L<<myport->mp_SigBit; /* Record the signal bits */
- sigmask = SIGBREAKF_CTRL_C | portsignal; /* for later use. */
-
- sp_write->dp_Type = ACTION_WRITE; /* Fill out the ACTION_WRITE packet. */
- sp_write->dp_Arg1 = out->fh_Arg1;
- sp_write->dp_Arg2 = (LONG)buf2; /* Arg2 points to the buffer to write */
- sp_write->dp_Arg3 = 0L; /* out. At first glance, it might */
- sp_write->dp_Res1 = 0L; /* seem odd to bother setting Arg2 */
- /* when the program hasn't read anything yet. */
- /* This is to set up for the main loop. The */
- /* main loop swaps the ACTION_READ buffer with */
- /* the ACTION_WRITE buffer when it receives */
- /* a completed read. Likewise, dp_Arg3 and */
- /* dp_Res1 are set to make the ACTION_READ */
- /* look like it has a valid return value so */
- /* main loop won't fail the first time through */
- /* the loop. */
- MainLoop();
- FreeDosObject(DOS_STDPKT, sp_write);
- }
- FreeDosObject(DOS_STDPKT, sp_read);
- }
- }
- }
- DeleteMsgPort(myport);
- }
- }
- }
-
-
- void MainLoop()
- {
- struct StandardPacket *mysp;
- UBYTE *buf;
-
- LONG amount_read;
-
- BOOL sp_read_busy = TRUE, /* Is the ACTION_READ packet busy? */
- sp_write_busy = FALSE, /* Is the ACTION_WRITE packet busy? */
- done = FALSE; /* Is the program finished? */
-
- /* main() has already taken care of sending the initial read to the */
- /* handler. Because we need the data from that read before we can */
- while (!done) /* do anything, the first thing to do is wait for its return. */
- {
- do /* Wait for the ACTION_READ to return. */
- {
- signals = Wait(sigmask); /* Wait for port signal or CTRL-C. */
-
- if (signals & portsignal) /* If a message arrived at the port, ... */
- {
- while (mysp = (struct StandardPacket *)GetMsg(myport)) /* ...empty the port. */
- {
- /* If this message is the ACTION_READ packet, mark it as */
- /* no longer busy so we can use it to start another read. */
- if (mysp->sp_Pkt.dp_Type == ACTION_READ) sp_read_busy = FALSE;
-
- /* If this message is instead the ACTION_WRITE packet, */
- /* mark it as not busy. We need to check for this because */
- /* the WRITE_PACKET from the previous interation through */
- /* the loop might have come back before the ACTION_WRITE */
- /* from the previous interation. */
- else
- if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
- }
- }
-
- if (signals & SIGBREAKF_CTRL_C) /* If someone hit CTRL-C, start to quit. */
- {
- done = TRUE; /* If the ACTION_READ is still out, try to */
- if (sp_read_busy) /* abort it. As of V39, AbortPkt() does */
- AbortPkt(in->fh_Type, sp_read); /* not do anything, so this function has */
- } /* no effect. Maybe a later release of the */
- /* OS will support packet aborting. */
-
-
- } while (sp_read_busy); /* End of "wait for ACTION_READ" loop. */
-
- /* Get ready to send the next ACTION_READ. */
- buf = (UBYTE *)(sp_read->dp_Arg2); /* Hold on to the important stuff from the */
- amount_read = sp_read->dp_Res1; /* ACTION_READ we just got back so we can */
- /* reuse the packet to start a new read */
- /* while processing the last read's data. */
-
- while (sp_write_busy) /* Because this example only uses two buffers and */
- { /* the ACTION_WRITE might be using one of them, */
- /* this example has to wait for an outstanding */
- /* ACTION_WRITE to return before reusing the */
- /* ACTION_WRITE packet's buffer. */
- signals = Wait(sigmask);
-
- if (signals & portsignal) /* If a message arrived at the port, ... */
- { /* ... empty the port. */
- while (mysp = (struct StandardPacket *)GetMsg(myport))
- if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
- }
-
- if (signals & SIGBREAKF_CTRL_C) /* If someone hit CTRL-C, start to quit. */
- {
- done = TRUE; /* If the ACTION_READ is still out, try to */
- if (sp_write_busy) AbortPkt(out->fh_Type, sp_write); /* abort it. */
- }
- }
-
- /* Make sure the user didn't hit CTRL-C. If the user hit CTRL-C dur- */
- if (!done) /* ing one of the "wait for packet" loops, done == TRUE. Notice that */
- { /* this example does not actually break for the CTRL-C until after it */
- /* gets back both packets. */
-
- /* This tests the return values from the ACTION_READ and ACTION_WRITE */
- /* packets. The ACTION_READ packet returns the number of bytes it */
- /* read in dp_Res1, which was copied earlier into amount_read. If it */
- /* is 0, the read packet found the EOF. If it is negative, there was */
- /* an error. In the case of ACTION_WRITE, an error occurs if the */
- /* number of bytes that ACTION_WRITE was supposed to write (Arg3) */
- /* does not match the actual number it wrote, which ACTION_WRITE re- */
- /* turns in Res1. This test is the reason dp_Res1 and dp_Arg3 were */
- /* set to zero when the ACTION_WRITE packet was set up in main(). */
- if ((amount_read > 0) && (sp_write->dp_Res1 == sp_write->dp_Arg3))
- {
- sp_read->dp_Arg2 = sp_write->dp_Arg2; /* ACTION_WRITE is finished with its */
- /* buffer, use it in the next read. */
-
- SendPkt(sp_read, in->fh_Type, myport); /* Send the next ACTION_READ and mark */
- sp_read_busy = TRUE; /* the ACTION_READ as busy. */
-
- /* Process Buffer. This example doesn't do anything with the data from the */
- /* last ACTION_READ, it just passes it on to the STDOUT handler. */
-
-
- sp_write->dp_Arg2 = (LONG)buf; /* Set up the ACTION_WRITE packet. */
- sp_write->dp_Arg3 = amount_read;
- SendPkt(sp_write, out->fh_Type, myport); /* Send the next ACTION_WRITE and */
- sp_write_busy = TRUE; /* mark the ACTION_WRITE as busy. */
- }
- else /* A packet returned with a failure, so quit. */
- done = TRUE;
- }
- }
- }
-